Skip to content

Comments

🥅 Successfully parse invalid response code data#614

Merged
nevans merged 2 commits intomasterfrom
parser/invalid-resp-text-code-data
Feb 20, 2026
Merged

🥅 Successfully parse invalid response code data#614
nevans merged 2 commits intomasterfrom
parser/invalid-resp-text-code-data

Conversation

@nevans
Copy link
Collaborator

@nevans nevans commented Feb 19, 2026

When the parser encounters a recoverable error in resp-text-code, it now returns InvalidParseData to represent the data that we've skipped over. InvalidParseData can be used for similar recoverable parse errors in the future (for example, many servers respond with invalid BODYSTRUCTURE or incorrectly escaped quoted strings).

The specific example I have encountered the most is when Microsoft's IMAP servers send an invalid COPYUID response code. Although it is invalid for resp-code-copy, it's still a valid resp-text-code because it does match atom [SP 1*<any TEXT-CHAR except "]">].

This creates some minor differences for invalid resp-text-code data:

  • <= v0.6.2: raises ResponseParseError (this is a bug).
  • == v0.6.3: returns ResponseText with no ResponseCode (also a bug).
  • >= v0.6.4: returns ResponseText with code with InvalidParseData.

Although this is a bugfix, it has a minor incompatibility for response handlers which assume that a particular ResponseCode#name always results in the same type of ResponseCode#data.

# This was previously a safe assumption
imap.add_response_handler do |resp|
  if resp in {data: {code: {name: "COPYUID", data: copyuid}}}
    copyuid => Net::IMAP::CopyUIDData
  end
end

# With this change, ResponseCode#data could also be InvalidParseData
imap.add_response_handler do |resp|
  if resp in {data: {code: {name: "COPYUID", data: copyuid}}}
    copyuid => Net::IMAP::CopyUIDData | Net::IMAP::InvalidParseData
  end
end

Prior to v0.6.3, these responses would raise a ResponseParseError and the response handler would not have been called.

I've updated the ResponseCode rdoc with the following, even broader declaration:

      # When ResponseParser does not know how to parse the response code data,
      # #data may return the unparsed string, ExtensionData, or UnparsedData.
      # When ResponseParser attempts but fails to parse the response code data,
      # #data returns InvalidParseData.

@nevans nevans added the bug Something isn't working label Feb 19, 2026
@nevans nevans force-pushed the parser/invalid-resp-text-code-data branch 2 times, most recently from 191d716 to 1efb90e Compare February 19, 2026 19:26
@nevans
Copy link
Collaborator Author

nevans commented Feb 20, 2026

@hoffi This is follow-up to #601/#597, and addresses #601 (comment).

I intend to release this with v0.6.4. Some might see this as a "backward incompatibility" (as described the PR description). But, in my opinion, this is a bugfix and I don't intend to put this behavior behind a config flag. Let me know if you think otherwise.

@nevans nevans force-pushed the parser/invalid-resp-text-code-data branch 2 times, most recently from 4e5be14 to 3c64122 Compare February 20, 2026 20:09
When the parser encounters a recoverable error in `resp-text-code`, it
now returns `InvalidParseData` to represent the data that we've skipped
over.  `InvalidParseData` can be used for similar recoverable parse
errors in the future (for example, many servers respond with invalid
`BODYSTRUCTURE` or incorrectly escaped quoted strings).

The specific example I have encountered the most is when Microsoft's
IMAP servers send an invalid COPYUID response code.  Although it is
invalid for `resp-code-copy`, it's still a valid `resp-text-code`
because it does match `atom [SP 1*<any TEXT-CHAR except "]">]`.

This creates some minor differences for invalid `resp-text-code` data:
* <= v0.6.2: raises ResponseParseError (this is a bug).
* == v0.6.3: returns ResponseText with no ResponseCode (also a bug).
* >= v0.6.4: returns ResponseText with code with InvalidParseData.

Although this is a bugfix, it has a minor incompatibility for response
handlers which assume that a particular `ResponseCode#name` always
results in the same type of `ResponseCode#data`.

```ruby
  # It was previously safe to assume the class of #data, based on #name:
  imap.add_response_handler do |resp|
    if resp in {data: {code: {name: "COPYUID", data: opyuid}}}
      copyuid => Net::IMAP::CopyUIDData
    end
  end

  # With this change, ResponseCode#data could also be InvalidParseData
  imap.add_response_handler do |resp|
    if resp in {data: {code: {name: "COPYUID", data: copyuid}}}
      copyuid => Net::IMAP::CopyUIDData | Net::IMAP::InvalidParseData
    end
  end
```

Prior to v0.6.3, these responses would raise a ResponseParseError and
the response handler would not have been called.
@nevans nevans force-pushed the parser/invalid-resp-text-code-data branch from 3c64122 to 7f0e115 Compare February 20, 2026 20:23
@nevans nevans merged commit 0b6129d into master Feb 20, 2026
39 checks passed
@nevans nevans deleted the parser/invalid-resp-text-code-data branch February 20, 2026 20:36
@hoffi
Copy link
Contributor

hoffi commented Feb 20, 2026

@nevans yes this looks fine for me. 👍 Personally I do appreciate it that the response code contains a hint that the response contained data that could not be parsed properly so I could maybe handle this case individually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants